"""
配置验证器模块

提供独立的配置验证功能，支持多种验证规则和错误报告。
"""

import logging
from typing import Dict, Any, List, Tuple, Optional
from pathlib import Path


class ConfigValidator:
    """配置验证器类
    
    提供独立的配置验证功能，支持多种验证规则。
    """
    
    def __init__(self, logger: Optional[logging.Logger] = None):
        """初始化配置验证器
        
        参数:
            logger (Optional[logging.Logger]): 日志记录器，如果为None则创建默认记录器
        """
        if logger:
            self.logger = logger
        else:
            self.logger = self._setup_default_logging()
        
        # 定义验证规则
        self.validation_rules = {
            'required_fields': self._validate_required_fields,
            'database_type': self._validate_database_type,
            'port_range': self._validate_port_range,
            'path_strings': self._validate_path_strings,
            'boolean_fields': self._validate_boolean_fields,
            'encryption_config': self._validate_encryption_config
        }
    
    def _setup_default_logging(self) -> logging.Logger:
        """设置默认日志记录器
        
        返回:
            logging.Logger: 配置好的日志记录器
        """
        logger = logging.getLogger("database_backup.config_validator")
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)
        return logger
    
    def validate_config(self, config: Dict[str, Any]) -> Tuple[bool, List[str]]:
        """验证配置
        
        参数:
            config (Dict[str, Any]): 要验证的配置
        
        返回:
            Tuple[bool, List[str]]: (是否有效, 错误消息列表)
        """
        errors = []
        
        # 执行所有验证规则
        for rule_name, rule_func in self.validation_rules.items():
            try:
                rule_errors = rule_func(config)
                if rule_errors:
                    errors.extend(rule_errors)
            except Exception as e:
                self.logger.error(f"验证规则 {rule_name} 执行失败: {e}")
                errors.append(f"验证规则 {rule_name} 执行失败: {e}")
        
        is_valid = len(errors) == 0
        return is_valid, errors
    
    def validate_config_file(self, config_file: str) -> Tuple[bool, List[str]]:
        """验证配置文件
        
        参数:
            config_file (str): 配置文件路径
        
        返回:
            Tuple[bool, List[str]]: (是否有效, 错误消息列表)
        """
        try:
            # 加载配置文件
            config_path = Path(config_file)
            if not config_path.exists():
                return False, [f"配置文件不存在: {config_file}"]
            
            import tomllib
            with open(config_path, 'rb') as f:
                config = tomllib.load(f)
            
            # 添加配置文件名信息
            config['_config_file'] = str(config_path)
            config['_config_name'] = config_path.stem
            
            return self.validate_config(config)
            
        except Exception as e:
            error_msg = f"加载配置文件失败 {config_file}: {e}"
            self.logger.error(error_msg)
            return False, [error_msg]
    
    def _validate_required_fields(self, config: Dict[str, Any]) -> List[str]:
        """验证必需字段
        
        参数:
            config (Dict[str, Any]): 配置信息
        
        返回:
            List[str]: 错误消息列表
        """
        errors = []
        
        # 检查数据库类型
        if 'type' not in config:
            errors.append("配置缺少必需字段: type")
        
        # 检查数据库连接配置
        if 'database' not in config:
            errors.append("配置缺少必需字段: database")
        else:
            db_config = config['database']
            required_db_fields = ['host', 'port', 'database', 'username', 'password']
            
            for field in required_db_fields:
                if field not in db_config:
                    errors.append(f"配置缺少必需字段: {field}")
        
        return errors
    
    def _validate_database_type(self, config: Dict[str, Any]) -> List[str]:
        """验证数据库类型
        
        参数:
            config (Dict[str, Any]): 配置信息
        
        返回:
            List[str]: 错误消息列表
        """
        errors = []
        
        if 'type' in config:
            valid_types = ['mysql', 'postgresql', 'mariadb']
            if config['type'] not in valid_types:
                errors.append(f"不支持的数据库类型: {config['type']}")
        
        return errors
    
    def _validate_port_range(self, config: Dict[str, Any]) -> List[str]:
        """验证端口号范围
        
        参数:
            config (Dict[str, Any]): 配置信息
        
        返回:
            List[str]: 错误消息列表
        """
        errors = []
        
        if 'database' in config:
            db_config = config['database']
            port = db_config.get('port')
            
            if port is not None:
                try:
                    port_int = int(port)
                    if port_int < 1 or port_int > 65535:
                        errors.append(f"端口号超出范围: {port_int}")
                except (ValueError, TypeError):
                    errors.append(f"端口号格式无效: {port}")
        
        return errors
    
    def _validate_path_strings(self, config: Dict[str, Any]) -> List[str]:
        """验证路径字符串
        
        参数:
            config (Dict[str, Any]): 配置信息
        
        返回:
            List[str]: 错误消息列表
        """
        errors = []
        
        if 'paths' in config:
            paths_config = config['paths']
            
            if 'git_root_dir' in paths_config:
                git_root_dir = paths_config['git_root_dir']
                if not git_root_dir or not isinstance(git_root_dir, str):
                    errors.append("git_root_dir必须是非空字符串")
            
            if 'backup_dir' in paths_config:
                backup_dir = paths_config['backup_dir']
                if not backup_dir or not isinstance(backup_dir, str):
                    errors.append("backup_dir必须是非空字符串")
        
        return errors
    
    def _validate_boolean_fields(self, config: Dict[str, Any]) -> List[str]:
        """验证布尔值字段
        
        参数:
            config (Dict[str, Any]): 配置信息
        
        返回:
            List[str]: 错误消息列表
        """
        errors = []
        
        if 'advanced' in config:
            advanced_config = config['advanced']
            
            if 'compress' in advanced_config:
                compress = advanced_config['compress']
                if not isinstance(compress, bool):
                    errors.append("compress必须是布尔值")
            
            if 'encrypt' in advanced_config:
                encrypt = advanced_config['encrypt']
                if not isinstance(encrypt, bool):
                    errors.append("encrypt必须是布尔值")
        
        return errors
    
    def _validate_encryption_config(self, config: Dict[str, Any]) -> List[str]:
        """验证加密配置
        
        参数:
            config (Dict[str, Any]): 配置信息
        
        返回:
            List[str]: 错误消息列表
        """
        errors = []
        
        if 'advanced' in config:
            advanced_config = config['advanced']
            
            if 'encrypt' in advanced_config and advanced_config['encrypt']:
                encrypt_password = advanced_config.get('encrypt_password', '')
                if not encrypt_password or not isinstance(encrypt_password, str):
                    errors.append("启用加密时必须设置encrypt_password")
        
        return errors
    
    def get_validation_summary(self, config: Dict[str, Any]) -> Dict[str, Any]:
        """获取验证摘要
        
        参数:
            config (Dict[str, Any]): 配置信息
        
        返回:
            Dict[str, Any]: 验证摘要信息
        """
        is_valid, errors = self.validate_config(config)
        
        summary = {
            'is_valid': is_valid,
            'error_count': len(errors),
            'errors': errors,
            'config_name': config.get('_config_name', 'unknown'),
            'config_file': config.get('_config_file', 'unknown')
        }
        
        return summary


def create_config_validator(logger: Optional[logging.Logger] = None) -> ConfigValidator:
    """创建配置验证器实例
    
    参数:
        logger (Optional[logging.Logger]): 日志记录器
    
    返回:
        ConfigValidator: 配置验证器实例
    """
    return ConfigValidator(logger)